using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Cryptography;
using System.Text;
using OracleInternal.I18N;
using OracleInternal.Secure.Encryption;

namespace OracleInternal.Secure.Logon
{
	internal sealed class O5LogonHelper
	{
		private const byte m_a = 2;

		private const byte m_b = 32;

		private static int c;

		private static int d;

		private const string e = "AUTH_PBKDF2_SPEEDY_KEY";

		private static byte[] f;

		private const byte g = 1;

		private const byte h = 2;

		private const long i = 2428144662L;

		private const long j = 1571793352L;

		private const long k = 4019742287L;

		private const long l = 4276506107L;

		private const long m = 378321552L;

		private const long n = 3366563677L;

		private const long o = 1332123887L;

		private const long p = 4216186622L;

		internal const int q = 2361;

		internal const int r = 6949;

		internal const int s = 18453;

		internal static byte[] t;

		static O5LogonHelper()
		{
			c = 16;
			d = 128;
			f = new byte[d / 8];
			t = null;
			t = Encoding.ASCII.GetBytes("AUTH_PBKDF2_SPEEDY_KEY");
		}

		internal static bool DoLogonProcessing(Conv dbCharSetConv, int verifierType, byte[] salt, byte logonCompatibility, string noQuotesUser, SecureString securePassword, byte[] encryptedSK, byte[] pbkdf2_csk_salt, int pbkdf2_vgen_count, int auth_pbkdf2_sder_count, bool bSvrCSMultibyte, out byte[] encryptedKB, out byte[] encryptedPassword, out byte[] newKey, out byte[] confounder, out byte[] pbkdf2_speedy_key)
		{
			return a(dbCharSetConv, verifierType, salt, logonCompatibility, noQuotesUser, securePassword, encryptedSK, pbkdf2_csk_salt, pbkdf2_vgen_count, auth_pbkdf2_sder_count, bSvrCSMultibyte, out encryptedKB, out encryptedPassword, out newKey, out confounder, out pbkdf2_speedy_key);
		}

		internal static void ProcessNewPassword(Conv dbCharSetConv, string pwdEncStr, SecureString secureNewPassword, byte[] encKey, out byte[] password, ref byte[] confounder)
		{
			a(dbCharSetConv, pwdEncStr, secureNewPassword, encKey, out password, ref confounder);
		}

		internal static byte[] EvaluateServerResponse(string cipherStr, byte[] key, byte[] msgHex)
		{
			return b(cipherStr, key, msgHex);
		}

		internal static byte[] EncryptOraAuthJDWPValue(bool bExternalAuthentication, ushort serverOne, byte[] key, byte[] valueToEncrypt)
		{
			return a(bExternalAuthentication, serverOne, key, valueToEncrypt);
		}

		private static bool a(Conv A_0, int A_1, byte[] A_2, byte A_3, string A_4, SecureString A_5, byte[] A_6, byte[] A_7, int A_8, int A_9, bool A_10, out byte[] A_11, out byte[] A_12, out byte[] A_13, out byte[] A_14, out byte[] A_15)
		{
			bool result = true;
			int num = 0;
			byte[] array = null;
			int num2 = 0;
			int num3 = 0;
			int num4 = 16;
			string text = null;
			string a_ = "AES/CBC/PKCS5Padding";
			A_11 = null;
			A_12 = null;
			A_13 = null;
			A_14 = null;
			A_15 = null;
			RNGCryptoServiceProvider rNGCryptoServiceProvider = null;
			char[] array2 = null;
			byte[] array3 = null;
			byte[] array4 = null;
			if (2361 == A_1 || 6949 == A_1 || 18453 == A_1)
			{
				try
				{
					if (A_5 == null || A_5.Length <= 0)
					{
						return false;
					}
					IntPtr intPtr = IntPtr.Zero;
					GCHandle gCHandle;
					try
					{
						intPtr = Marshal.SecureStringToGlobalAllocUnicode(A_5);
						array2 = new char[A_5.Length];
						gCHandle = GCHandle.Alloc(array2, GCHandleType.Pinned);
						Marshal.Copy(intPtr, array2, 0, array2.Length);
					}
					finally
					{
						if (IntPtr.Zero != intPtr)
						{
							Marshal.ZeroFreeGlobalAllocUnicode(intPtr);
							intPtr = IntPtr.Zero;
						}
					}
					int byteCount = A_0.GetBytesLength(array2, 0, array2.Length);
					array3 = new byte[byteCount];
					GCHandle gCHandle2 = GCHandle.Alloc(array3, GCHandleType.Pinned);
					A_0.ConvertCharsToBytes(array2, 0, array2.Length, array3, 0, ref byteCount);
					GCHandle gCHandle3;
					if (2361 != A_1)
					{
						byteCount = Encoding.UTF8.GetByteCount(array2, 0, array2.Length);
						array4 = new byte[byteCount];
						gCHandle3 = GCHandle.Alloc(array4, GCHandleType.Pinned);
						Encoding.UTF8.GetBytes(array2, 0, array2.Length, array4, 0);
						for (int i = 0; i < array2.Length; i++)
						{
							array2[i] = '\0';
						}
						array2 = null;
						gCHandle.Free();
					}
					else
					{
						gCHandle3 = GCHandle.Alloc(new byte[0]);
					}
					if (2361 == A_1)
					{
						gCHandle3.Free();
						num = 16;
						num2 = 16;
						num3 = 64;
						text = "AES/CBC/NoPadding";
						byte[] sourceArray = new WorkBench().b(A_4, array2, 0, array2.Length - 1, A_10);
						for (int j = 0; j < array2.Length; j++)
						{
							array2[j] = '\0';
						}
						array2 = null;
						gCHandle.Free();
						array = new byte[num];
						Array.Copy(sourceArray, 0, array, 0, 8);
						for (int k = 8; k < 16; k++)
						{
							array[k] = 0;
						}
					}
					else if (6949 != A_1)
					{
						if (18453 != A_1)
						{
							return false;
						}
						num = 32;
						num2 = 32;
						text = "AES/CBC/NoPadding";
						byte[] array5 = a(Encoding.ASCII.GetString(A_2));
						byte[] array6 = new byte[array5.Length + t.Length];
						Array.Copy(array5, array6, array5.Length);
						Array.Copy(t, 0, array6, array5.Length, t.Length);
						SHA512CryptoServiceProvider sHA512CryptoServiceProvider = null;
						Class_i i2 = null;
						array = new byte[num];
						try
						{
							FieldInfo? field = typeof(HMACSHA512).GetField("KeyValue", BindingFlags.Instance | BindingFlags.NonPublic);
							HMACSHA512 hMACSHA = new HMACSHA512(array4);
							i2 = new Class_i(hMACSHA, array6, A_8);
							byte[] array7 = (byte[])field!.GetValue(hMACSHA);
							GCHandle gCHandle4 = GCHandle.Alloc(array7, GCHandleType.Pinned);
							for (int l = 0; l < array4.Length; l++)
							{
								array4[l] = 0;
							}
							array4 = null;
							gCHandle3.Free();
							A_15 = i2.a(64);
							for (int m = 0; m < array7.Length; m++)
							{
								array7[m] = 0;
							}
							array7 = null;
							gCHandle4.Free();
							if (i2 != null)
							{
								i2.Dispose();
								i2 = null;
							}
							sHA512CryptoServiceProvider = new SHA512CryptoServiceProvider();
							byte[] array8 = new byte[A_15.Length + array5.Length];
							Array.Copy(A_15, 0, array8, 0, A_15.Length);
							Array.Copy(array5, 0, array8, A_15.Length, array5.Length);
							Array.Copy(sHA512CryptoServiceProvider.ComputeHash(array8), 0, array, 0, num);
						}
						finally
						{
							if (sHA512CryptoServiceProvider != null)
							{
								sHA512CryptoServiceProvider.Clear();
								sHA512CryptoServiceProvider.Dispose();
							}
							i2?.Dispose();
						}
					}
					else
					{
						num = 24;
						num2 = 24;
						num3 = 96;
						text = (((A_3 & 2) == 0) ? "AES/CBC/PKCS5Padding" : "AES/CBC/NoPadding");
						HashAlgorithm hashAlgorithm = null;
						byte[] array9 = null;
						array = new byte[num];
						try
						{
							hashAlgorithm = new SHA1CryptoServiceProvider();
							byte[] array10 = a(Encoding.ASCII.GetString(A_2));
							byte[] array11 = new byte[array4.Length + array10.Length];
							GCHandle gCHandle5 = GCHandle.Alloc(array11, GCHandleType.Pinned);
							Array.Copy(array4, 0, array11, 0, array4.Length);
							Array.Copy(array10, 0, array11, array4.Length, array10.Length);
							if (array4 != null)
							{
								for (int n = 0; n < array4.Length; n++)
								{
									array4[n] = 0;
								}
								array4 = null;
							}
							gCHandle3.Free();
							array9 = hashAlgorithm.ComputeHash(array11);
							for (int num5 = 0; num5 < array11.Length; num5++)
							{
								array11[num5] = 0;
							}
							array11 = null;
							gCHandle5.Free();
							Array.Copy(array9, 0, array, 0, array9.Length);
						}
						finally
						{
							if (hashAlgorithm != null)
							{
								hashAlgorithm.Clear();
								hashAlgorithm.Dispose();
							}
						}
					}
					byte[] array12 = b(text, array, A_6);
					rNGCryptoServiceProvider = new RNGCryptoServiceProvider();
					if (array12 != null && array12.Length < num2)
					{
						array12 = new byte[num2];
						rNGCryptoServiceProvider.GetBytes(array12);
					}
					byte[] array13 = new byte[array12.Length];
					rNGCryptoServiceProvider.GetBytes(array13);
					byte[] a_2 = a(text, array, array13);
					if (A_11 == null || A_11.Length != num3)
					{
						A_11 = new byte[A_6.Length];
						rNGCryptoServiceProvider.GetBytes(A_11);
					}
					a(a_2, A_11, 0);
					A_13 = a(A_1, array12, c, array13, c, A_7, A_9, A_3);
					if (A_13.Length != num2)
					{
						A_13 = new byte[num2];
						rNGCryptoServiceProvider.GetBytes(A_13);
					}
					A_14 = new byte[num4];
					rNGCryptoServiceProvider.GetBytes(A_14);
					byte[] array14 = new byte[num4 + array3.Length];
					GCHandle gCHandle6 = GCHandle.Alloc(array14, GCHandleType.Pinned);
					Array.Copy(A_14, 0, array14, 0, num4);
					Array.Copy(array3, 0, array14, num4, array3.Length);
					for (int num6 = 0; num6 < array3.Length; num6++)
					{
						array3[num6] = 0;
					}
					array3 = null;
					gCHandle2.Free();
					byte[] array15 = a(a_, A_13, array14);
					for (int num7 = 0; num7 < array14.Length; num7++)
					{
						array14[num7] = 0;
					}
					array14 = null;
					gCHandle6.Free();
					if (array15 != null)
					{
						A_12 = new byte[array15.Length * 2];
						a(array15, A_12, 0);
					}
					if (18453 != A_1)
					{
						return result;
					}
					byte[] array16 = new byte[num4];
					rNGCryptoServiceProvider.GetBytes(array16);
					byte[] array17 = new byte[num4 + A_15.Length];
					Array.Copy(array16, 0, array17, 0, num4);
					Array.Copy(A_15, 0, array17, num4, A_15.Length);
					byte[] array18 = a(text, A_13, array17);
					if (array18 == null)
					{
						return result;
					}
					A_15 = new byte[array18.Length * 2];
					a(array18, A_15, 0);
					return result;
				}
				catch (Exception)
				{
					return false;
				}
				finally
				{
					rNGCryptoServiceProvider?.Dispose();
				}
			}
			return result;
		}

		private static byte[] a(int A_0, byte[] A_1, int A_2, byte[] A_3, int A_4, byte[] A_5, int A_6, byte A_7)
		{
			byte[] array = null;
			byte[] array2 = null;
			int num = 0;
			byte[] array3 = null;
			MD5CryptoServiceProvider mD5CryptoServiceProvider = null;
			Class_i i = null;
			try
			{
				switch (A_0)
				{
				case 2361:
				{
					num = 16;
					if ((A_7 & 0x20u) != 0)
					{
						byte[] array6 = new byte[num * 2];
						Array.Copy(A_3, 0, array6, 0, A_3.Length / 2);
						Array.Copy(A_1, 0, array6, A_3.Length / 2, A_1.Length / 2);
						array3 = new byte[array6.Length * 2];
						a(array6, array3, 0);
						break;
					}
					mD5CryptoServiceProvider = new MD5CryptoServiceProvider();
					mD5CryptoServiceProvider.Initialize();
					array2 = new byte[num];
					for (int j = 0; j < num; j++)
					{
						array2[j] = (byte)(A_1[j + A_2] ^ A_3[j + A_4]);
					}
					array = mD5CryptoServiceProvider.ComputeHash(array2);
					break;
				}
				case 6949:
					num = 24;
					if ((A_7 & 0x20) == 0)
					{
						mD5CryptoServiceProvider = new MD5CryptoServiceProvider();
						mD5CryptoServiceProvider.Initialize();
						array2 = new byte[num];
						for (int j = 0; j < num; j++)
						{
							array2[j] = (byte)(A_1[j + A_2] ^ A_3[j + A_4]);
						}
						array = new byte[24];
						Array.Copy(mD5CryptoServiceProvider.ComputeHash(array2, 0, 16), 0, array, 0, 16);
						mD5CryptoServiceProvider.Initialize();
						Array.Copy(mD5CryptoServiceProvider.ComputeHash(array2, 16, 8), 0, array, 16, 8);
					}
					else
					{
						byte[] array5 = new byte[num * 2];
						Array.Copy(A_3, 0, array5, 0, num);
						Array.Copy(A_1, 0, array5, num, num);
						array3 = new byte[array5.Length * 2];
						a(array5, array3, 0);
					}
					break;
				case 18453:
				{
					num = 32;
					byte[] array4 = new byte[A_1.Length + A_3.Length];
					Array.Copy(A_3, 0, array4, 0, A_3.Length);
					Array.Copy(A_1, 0, array4, A_3.Length, A_1.Length);
					array3 = new byte[array4.Length * 2];
					a(array4, array3, 0);
					break;
				}
				default:
					return new byte[0];
				}
				if (array3 == null)
				{
					return array;
				}
				if ((A_7 & 0x20) == 0)
				{
					return array;
				}
				A_5 = a(Encoding.ASCII.GetString(A_5));
				i = new Class_i(new HMACSHA512(array3), A_5, A_6);
				return i.a(num);
			}
			finally
			{
				if (mD5CryptoServiceProvider != null)
				{
					mD5CryptoServiceProvider.Clear();
					mD5CryptoServiceProvider.Dispose();
				}
				i?.Dispose();
			}
		}

		private static byte[] b(string A_0, byte[] A_1, byte[] A_2)
		{
			if (A_1 == null)
			{
				return new byte[0];
			}
			byte[] result = new byte[0];
			AesCryptoServiceProvider aesCryptoServiceProvider = new AesCryptoServiceProvider();
			try
			{
				if (!A_0.Contains("PKCS5Padding"))
				{
					aesCryptoServiceProvider.Padding = PaddingMode.None;
				}
				else
				{
					aesCryptoServiceProvider.Padding = PaddingMode.PKCS7;
				}
				aesCryptoServiceProvider.Mode = CipherMode.CBC;
				aesCryptoServiceProvider.KeySize = A_1.Length * 8;
				aesCryptoServiceProvider.BlockSize = d;
				aesCryptoServiceProvider.Key = A_1;
				aesCryptoServiceProvider.IV = f;
				ICryptoTransform cryptoTransform = aesCryptoServiceProvider.CreateDecryptor();
				byte[] array = a(Conv.GetInstance(871).ConvertBytesToString(A_2, 0, A_2.Length));
				result = cryptoTransform.TransformFinalBlock(array, 0, array.Length);
				return result;
			}
			catch
			{
				return result;
			}
			finally
			{
				aesCryptoServiceProvider.Clear();
				aesCryptoServiceProvider.Dispose();
			}
		}

		private static byte[] a(string A_0, byte[] A_1, byte[] A_2)
		{
			if (A_1 == null)
			{
				return new byte[0];
			}
			byte[] result = null;
			AesCryptoServiceProvider aesCryptoServiceProvider = new AesCryptoServiceProvider();
			try
			{
				if (A_0.Contains("PKCS5Padding"))
				{
					aesCryptoServiceProvider.Padding = PaddingMode.PKCS7;
				}
				else if (A_0.Contains("Zeros"))
				{
					aesCryptoServiceProvider.Padding = PaddingMode.Zeros;
				}
				else
				{
					aesCryptoServiceProvider.Padding = PaddingMode.None;
				}
				aesCryptoServiceProvider.Mode = CipherMode.CBC;
				aesCryptoServiceProvider.KeySize = A_1.Length * 8;
				aesCryptoServiceProvider.BlockSize = d;
				aesCryptoServiceProvider.Key = A_1;
				aesCryptoServiceProvider.IV = f;
				result = aesCryptoServiceProvider.CreateEncryptor().TransformFinalBlock(A_2, 0, A_2.Length);
				return result;
			}
			catch
			{
				return result;
			}
			finally
			{
				aesCryptoServiceProvider.Clear();
				aesCryptoServiceProvider.Dispose();
			}
		}

		private static void a(Conv A_0, string A_1, SecureString A_2, byte[] A_3, out byte[] A_4, ref byte[] A_5)
		{
			RNGCryptoServiceProvider rNGCryptoServiceProvider = null;
			A_4 = null;
			try
			{
				rNGCryptoServiceProvider = new RNGCryptoServiceProvider();
				int num = 16;
				if (A_5 == null)
				{
					A_5 = new byte[num];
					rNGCryptoServiceProvider.GetBytes(A_5);
				}
				IntPtr intPtr = IntPtr.Zero;
				char[] array = null;
				byte[] array2 = null;
				try
				{
					intPtr = Marshal.SecureStringToGlobalAllocUnicode(A_2);
					array = new char[A_2.Length];
					Marshal.Copy(intPtr, array, 0, array.Length);
				}
				finally
				{
					if (IntPtr.Zero != intPtr)
					{
						Marshal.ZeroFreeGlobalAllocUnicode(intPtr);
						intPtr = IntPtr.Zero;
					}
				}
				if (array.Length != 0)
				{
					int byteCount = A_0.GetBytesLength(array, 0, array.Length);
					array2 = new byte[byteCount];
					GCHandle gCHandle = GCHandle.Alloc(array2, GCHandleType.Pinned);
					A_0.ConvertCharsToBytes(array, 0, array.Length, array2, 0, ref byteCount);
					for (int i = 0; i < array.Length; i++)
					{
						array[i] = '\0';
					}
					array = null;
					byte[] array3 = new byte[num + array2.Length];
					Array.Copy(A_5, 0, array3, 0, num);
					Array.Copy(array2, 0, array3, num, array2.Length);
					for (int j = 0; j < array2.Length; j++)
					{
						array2[j] = 0;
					}
					array2 = null;
					gCHandle.Free();
					byte[] array4 = a(A_1, A_3, array3);
					for (int k = 0; k < array3.Length; k++)
					{
						array3[k] = 0;
					}
					array3 = null;
					if (array4 != null)
					{
						A_4 = new byte[array4.Length * 2];
						a(array4, A_4, 0);
					}
				}
			}
			finally
			{
				rNGCryptoServiceProvider?.Dispose();
			}
		}

		internal static string b(string A_0)
		{
			if (string.IsNullOrEmpty(A_0))
			{
				return A_0;
			}
			if (A_0.StartsWith("\"") && A_0.EndsWith("\""))
			{
				A_0 = A_0.Substring(1, A_0.Length - 2);
			}
			return A_0;
		}

		private static byte[] a(bool A_0, ushort A_1, byte[] A_2, byte[] A_3)
		{
			byte[] array = null;
			byte[] array2 = null;
			if (A_0)
			{
				TripleDESCryptoServiceProvider tripleDESCryptoServiceProvider = new TripleDESCryptoServiceProvider();
				byte[] array3 = new byte[16];
				new RNGCryptoServiceProvider().GetBytes(array3);
				tripleDESCryptoServiceProvider.IV = new byte[tripleDESCryptoServiceProvider.BlockSize / 8];
				tripleDESCryptoServiceProvider.Key = array3;
				tripleDESCryptoServiceProvider.Padding = PaddingMode.Zeros;
				tripleDESCryptoServiceProvider.Mode = CipherMode.CBC;
				array2 = tripleDESCryptoServiceProvider.CreateEncryptor().TransformFinalBlock(A_3, 0, A_3.Length);
				long[] array4 = new long[4];
				byte[] array5 = new byte[16];
				array = new byte[(array2.Length + array5.Length + 1) * 2];
				a(array2, array, 0);
				array4[0] = BitConverter.ToUInt32(array3, 0);
				array4[1] = BitConverter.ToUInt32(array3, 4);
				array4[2] = BitConverter.ToUInt32(array3, 8);
				array4[3] = BitConverter.ToUInt32(array3, 12);
				if (BitConverter.IsLittleEndian && A_1 == 256)
				{
					array4[0] ^= 2428144662L;
					array4[1] ^= 1571793352L;
					array4[2] ^= 4019742287L;
					array4[3] ^= 4276506107L;
				}
				else
				{
					array4[0] ^= 378321552L;
					array4[1] ^= 3366563677L;
					array4[2] ^= 1332123887L;
					array4[3] ^= 4216186622L;
				}
				Array.Copy(BitConverter.GetBytes(array4[0]), 0, array5, 0, 4);
				Array.Copy(BitConverter.GetBytes(array4[1]), 0, array5, 4, 4);
				Array.Copy(BitConverter.GetBytes(array4[2]), 0, array5, 8, 4);
				Array.Copy(BitConverter.GetBytes(array4[3]), 0, array5, 12, 4);
				a(array5, array, array2.Length * 2);
				array[^2] = a(0);
				array[^1] = a(2);
			}
			else
			{
				array2 = a("AES/CBC/Zeros", A_2, A_3);
				array = new byte[(array2.Length + 1) * 2];
				a(array2, array, 0);
				array[array2.Length * 2] = a(0);
				array[array2.Length * 2 + 1] = a(1);
			}
			return array;
		}

		private static byte a(byte A_0)
		{
			A_0 = (byte)(A_0 & 0xFu);
			return (byte)((A_0 >= 10) ? (A_0 - 10 + 65) : (A_0 + 48));
		}

		private static void a(byte[] A_0, byte[] A_1, int A_2)
		{
			for (int i = 0; i < A_0.Length; i++)
			{
				A_1[A_2 + i * 2] = a((byte)((A_0[i] & 0xF0) >> 4));
				A_1[A_2 + i * 2 + 1] = a((byte)(A_0[i] & 0xFu));
			}
		}

		private static byte[] a(string A_0)
		{
			byte[] array = new byte[A_0.Length / 2];
			for (int i = 0; i < A_0.Length / 2; i++)
			{
				byte b = Convert.ToByte(A_0.Substring(2 * i, 1), 16);
				int num = Convert.ToByte(A_0.Substring(2 * i + 1, 1), 16) | (b << 4);
				array[i] = (byte)num;
			}
			return array;
		}

		private static string a(byte[] A_0)
		{
			StringBuilder stringBuilder = new StringBuilder(A_0.Length * 2);
			if (A_0 != null)
			{
				for (int i = 0; i < A_0.Length; i++)
				{
					if (i == 0)
					{
						stringBuilder.Append("[");
					}
					stringBuilder.AppendFormat("{0:x2}", A_0[i]);
				}
				stringBuilder.Append("]");
			}
			return stringBuilder.ToString();
		}
	}
}
